using System;
using System.Net;
using Daemon.Common;
using Daemon.Common.Generator;
using Daemon.Model;
using Daemon.Repository.Contract;
using Daemon.Common.Database;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Configuration;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium;

namespace Daemon.Controllers
{
    [ApiController]
    [Route("api/Generator")]
    public class GeneratorV2Controller : ControllerBase
    {
        private readonly ApiDBContent _context;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IWebHostEnvironment _env;
        private readonly IDatabaseConfigRepository _databaseConfigRepository;
        private readonly IConfiguration _configuration;
        private readonly IGenerateConfigRepository _generateConfigRepository;
        public GeneratorV2Controller(IConfiguration configuration, IHttpContextAccessor httpContextAccessor, IWebHostEnvironment env, ApiDBContent context, IGenerateConfigRepository generateConfigRepository, IDatabaseConfigRepository databaseConfigRepository)
        {
            _databaseConfigRepository = databaseConfigRepository;
            _generateConfigRepository = generateConfigRepository;
            _httpContextAccessor = httpContextAccessor;
            _configuration = configuration;
            _context = context;
            _env = env;
        }

        [Route("GetTableList")]
        [HttpGet]
        public ResultModel<TableInfo> GetTableList(string tableName)
        {
            var databaseConfig = _databaseConfigRepository.FindAll().FirstOrDefault();
            _context.Database.GetDbConnection().ConnectionString = DatabaseHelper.GetConnectionString(databaseConfig.Ip, databaseConfig.Port, databaseConfig.UserName, databaseConfig.Password, databaseConfig.DatabaseName);
            var result = DatabaseHelper.GetTableList(databaseConfig.DatabaseName, _context);
            return new ResultModel<TableInfo>(HttpStatusCode.OK, string.IsNullOrEmpty(tableName) ? result : result.Where(r => r.TableName == tableName), null);
        }

        [Route("GetTableInfo")]
        [HttpGet]
        public ResultModel GetTableInfo(string tableName)
        {
            var databaseConfig = _databaseConfigRepository.FindAll().FirstOrDefault();
            _context.Database.GetDbConnection().ConnectionString = DatabaseHelper.GetConnectionString(databaseConfig.Ip, databaseConfig.Port, databaseConfig.UserName, databaseConfig.Password, databaseConfig.DatabaseName);
            var result = DatabaseHelper.GetTableInfo(tableName, databaseConfig.DatabaseName, _context);
            return new ResultModel(HttpStatusCode.OK, null, new List<TableInfo>() { result });
        }

        [Route(nameof(ValidateFileExist))]
        [HttpGet]
        public bool ValidateFileExist(string entityName, string filePath, string extension)
        {
            return System.IO.File.Exists($"{filePath}\\{entityName}{extension}");
        }

        [Route(nameof(GenerateFrontEntity))]
        [HttpPost]
        public ResultModel GenerateFrontEntity([FromBody] GeneratorRequest request)
        {
            var databaseConfig = _databaseConfigRepository.FindAll().FirstOrDefault();
            _context.Database.GetDbConnection().ConnectionString = DatabaseHelper.GetConnectionString(databaseConfig.Ip, databaseConfig.Port, databaseConfig.UserName, databaseConfig.Password, databaseConfig.DatabaseName);
            request.TableInfo = DatabaseHelper.GetTableInfo(request.TableInfo.TableName, databaseConfig.DatabaseName, _context);
            var templateFilePath = request.IsFrontCode ? @$"{_env.ContentRootPath}\\tpl\\front\\model.tpl" : @$"{_env.ContentRootPath}\\tpl\\Model.tpl";
            return new ResultModel(HttpStatusCode.OK, null, new List<string> { GeneratorHelper.GenerateEntityCode(request, templateFilePath, request.FilePath, request.IsFrontCode, request.IsGenerateFile) });
        }

        [Route(nameof(CommonGenerate))]
        [HttpPost]
        public ResultModel CommonGenerate([FromBody] GeneratorRequest request)
        {
            var databaseConfig = _databaseConfigRepository.FindAll().FirstOrDefault();
            _context.Database.GetDbConnection().ConnectionString = DatabaseHelper.GetConnectionString(databaseConfig.Ip, databaseConfig.Port, databaseConfig.UserName, databaseConfig.Password, databaseConfig.DatabaseName);
            request.TableInfo = DatabaseHelper.GetTableInfo(request.TableInfo.TableName, databaseConfig.DatabaseName, _context);
            var diffPath = request.IsFrontCode ? "\\Front" : "";
            var templateFilePath = @$"{_env.ContentRootPath}\\tpl{diffPath}\\{request.TemplateFileName}";
            return new ResultModel(HttpStatusCode.OK, null, new List<string> { GeneratorHelper.CommonGenerateBackEndCode(request, templateFilePath, request.FilePath, request.IsGenerateFile) });
        }

        [Route(nameof(GenerateTableIndex))]
        [HttpPost]
        public ResultModel GenerateTableIndex([FromBody] GeneratorRequest request)
        {
            var databaseConfig = _databaseConfigRepository.FindAll().FirstOrDefault();
            _context.Database.GetDbConnection().ConnectionString = DatabaseHelper.GetConnectionString(databaseConfig.Ip, databaseConfig.Port, databaseConfig.UserName, databaseConfig.Password, databaseConfig.DatabaseName);
            request.TableInfo = DatabaseHelper.GetTableInfo(request.TableInfo.TableName, databaseConfig.DatabaseName, _context);
            var templateFilePath = @$"{_env.ContentRootPath}\\tpl\\front\\index.tpl";
            return new ResultModel(HttpStatusCode.OK, null, new List<string> { GeneratorHelper.GenerateFrontTableIndex(request, templateFilePath, request.FilePath, request.IsGenerateFile) });
        }

        [Route(nameof(GenerateForm))]
        [HttpPost]
        public ResultModel GenerateForm([FromBody] Daemon.Model.ViewModel.GenerateFormRequest data)
        {
            var componentHtmlList = new List<string>();
            var variableList = new List<string>();
            var jToken = JToken.Parse(data.Schema);
            var widgetArray = jToken["properties"].ToArray();
            List<Component> components = new List<Component>();
            foreach (var json in widgetArray)
            {
                var widget = JsonConvert.DeserializeObject<Component>(json.First().ToString());
                components.Add(widget);
            }

            components.ForEach(component =>
            {
                var generator = GeneratorCodeFactory.GetGenerator(component.Widget);
                var generatorResponse = generator.DoGenerate(component);
                componentHtmlList.Add(generatorResponse.ComponentHtml);
                variableList.AddRange(generatorResponse.VariableList);
            });

            var templateFilePath = @$"{_env.ContentRootPath}\\tpl\\front\\formDesign.tpl";
            var result = GeneratorHelper.GenerateForm(templateFilePath, components, componentHtmlList, variableList);
            return new ResultModel(HttpStatusCode.OK, null, new List<string> { result });
        }

        [Route(nameof(GenerateScreenImg))]
        [HttpGet]
        public ResultModel GenerateScreenImg(int id)
        {
            var options = new ChromeOptions();
            options.AddArgument("--headless");
            options.AddArgument("--start-maximized");

            using (var driver = new ChromeDriver(options))
            {
                driver.Navigate().GoToUrl($"http://localhost:8000/form/formDesign/formPreview/{id}");
                var screenshot = ((ITakesScreenshot)driver).GetScreenshot();
                DirFile.CreateDir($"{_configuration.GetSection("fileAddress").Value}\\screenshot");
                screenshot.SaveAsFile($"{_configuration.GetSection("fileAddress").Value}\\screenshot\\screenshot{id}.png");
                Console.WriteLine("Screenshot saved successfully.");
            }
            var serverFilePath = $"http://{_configuration.GetSection("AppSettings:ip")?.Value}:{_configuration.GetSection("AppSettings:port")?.Value}/Daemon/screenshot/screenshot{id}.png";
            return new ResultModel(HttpStatusCode.OK, "", new List<string>() { serverFilePath });
        }
    }
}